/**
 * 发布订阅使用工厂模式
 * */
export function createEventEmitter<T extends readonly string[]>(events: T) {
  type EventName = T[number];

  class EventEmitTool {
    private events = new Map<EventName, Set<Function>>();

    constructor() {
      events.forEach(event => this.events.set(event, new Set()));
    }

    /**
     * 订阅事件
     * @param {string} eventName 事件名称
     * @param {function} callback 回调函数
     * */
    on(eventName: EventName, callback: Function) {
      const callbacks = this.events.get(eventName) || new Set();
      callbacks.add(callback);
      this.events.set(eventName, callbacks);
    }

    /**
     * 取消订阅
     * @param {string} eventName 事件名称
     * @param {function} callback 要移除的回调函数（不传则移除整个事件）
     * */
    off(eventName: EventName, callback: Function) {
      let callbacks: Function[] = Array.from(this.events.get(eventName) || new Set());
      if (callback) {
        callbacks = callbacks.filter(cb => cb !== callback);
        if (!callbacks.length) {
          this.events.delete(eventName);
        }
      } else {
        this.events.delete(eventName);
      }
    }

    /**
     * 发布事件
     * @param {string} eventName 事件名称
     * @param {any} args 传递给回调函数的参数
     * */
    emit(eventName: EventName, ...args: any[]) {
      const callbacks: Function[] = Array.from(this.events.get(eventName) || new Set());
      if (!callbacks.length) return;
      callbacks.forEach(callback => callback(...args));
    }
  }

  return new EventEmitTool();
}
